/**
 * @file sem.c
 * @author lcz (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2022-10-23
 *
 * @copyright Copyright (c) 2022
 *
 */

#include "ipc/sem.h"
#include "core/task.h"
#include "cpu/irq.h"
/**
 * 信号量初始化
 */
void sem_init(sem_t *sem, int init_count)
{
    sem->count = init_count;
    list_init(&(sem->wait_list));
}
/**
 * 申请信号量
 */
void sem_wait(sem_t *sem)
{

    irq_state_t state = irq_enter_protection();
    // 关中断保护
    if (sem->count > 0)
    {
        sem->count--;
    }
    else
    {
        task_t *curr = task_current();
        // 当前进程从就绪队列中取出
        task_set_block(curr);
        // 将该经常添加到等待队列
        list_insert_last(&sem->wait_list, &(curr->wait_node));
        task_dispatch();
    }
    irq_leave_protection(state);
}
/**
 * 释放信号量
 */
void sem_notify(sem_t *sem)
{
    // 需要保护
    irq_state_t state = irq_enter_protection();
    if (list_count(&sem->wait_list))
    {
        list_node_t *node = list_remove_first(&sem->wait_list);
        task_t *task = list_node_parent(node, task_t, wait_node);
        task_set_ready(task);
        task_dispatch();
    }
    else
    {
        sem->count++;
    }
    irq_leave_protection(state);
}
/**
 * 获取信号量的当前值
 */
int sem_count(sem_t *sem)
{
    // 需要保护
    irq_state_t state = irq_enter_protection();
    int count = sem->count;
    return count;
    irq_leave_protection(state);
}